using System;
using System.Collections.Generic;
using System.Reflection;

namespace SKBKontur.Serialization.Binding
{
    public abstract class ScalarBinder : Binder
    {
        protected string ColumnName;

        protected ScalarBinder(string columnName)
        {
            ColumnName = columnName;
        }

        protected ScalarBinder()
        {
        }

        public string GetPropertyKeyName(PropertyInfo propertyInfo)
        {
            return ColumnName ?? propertyInfo.Name;
        }

        public abstract byte[] SerializeValue(object value);
        public abstract object UnserializeValue(Type type, byte[] data);

        public override void Unbind(object objectToUnbind, string propertyName,
                                    ref Dictionary<string, byte[]> serializedData)
        {
            var propertyInfo = GetPropertyInfo(objectToUnbind, propertyName);
            object value = propertyInfo.GetGetMethod().Invoke(objectToUnbind, new object[0]);
            if (value == null)
                return;
            serializedData[ColumnName ?? propertyName] = SerializeValue(value);
        }

        public override void Bind(ref object objectToBind, string propertyName, Dictionary<string, byte[]> serializedData)
        {
            string keyName = ColumnName ?? propertyName;
            if (!serializedData.ContainsKey(keyName))
                return;
            MethodInfo method = GetPropertySetter(objectToBind, propertyName);
            object value = UnserializeValue(method.GetParameters()[0].ParameterType, serializedData[keyName]);
            method.Invoke(objectToBind, new[] { value });
            serializedData.Remove(keyName);
        }
    }
}